

// ACM模式
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void async function () {
    line = await readline()
    // 创建邻接矩阵
    let [m, n] = line.split(' ').map((i) => parseInt(i)),
        graph = new Array(m).fill(0).map(() => new Array(n).fill(0)),
        isVitited = new Array(m).fill(0).map(() => new Array(n).fill(false)),
        res = 0,
        index = 0;
    // 初始化邻接矩阵
    while (line = await readline()) {
        let row = line.split(' ').map((i) => parseInt(i))
        for (let i = 0; i < n; i++) {
            graph[index][i] = row[i]
        }
        index++
    }
    // 深度遍历矩阵元素
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (graph[i][j] === 1 && isVitited[i][j] === false) {
                // 标记为已访问
                isVitited[i][j] = true
                // 未访问到的陆地+1
                res++
                // 遍历此陆地连接的陆地
                dfs(graph, isVitited, i, j)
            }
        }
    }
    console.log(res)
}()

function dfs(graph, isVitited, i, j) {
    let direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    for (let [x, y] of direction) {
        let nextI = i + x,
            nextY = j + y;
        if (nextI < 0 || nextI >= graph.length || nextY < 0 || nextY >= graph[0].length) continue
        if (graph[nextI][nextY] === 1 && isVitited[nextI][nextY] === false) {
            isVitited[nextI][nextY] = true
            dfs(graph, isVitited, nextI, nextY)
        }
    }
}




void async function () {
    line = await readline()
    // 创建邻接矩阵
    let [m, n] = line.split(' ').map((i) => parseInt(i)),
        graph = new Array(m).fill(0).map(() => new Array(n).fill(0)),
        isVitited = new Array(m).fill(0).map(() => new Array(n).fill(false)),
        res = 0,
        index = 0;
    // 初始化邻接矩阵
    while (line = await readline()) {
        let row = line.split(' ').map((i) => parseInt(i))
        for (let i = 0; i < n; i++) {
            graph[index][i] = row[i]
        }
        index++
    }
    for (let i = 0; i < m; i++) {
        for (let j = 0; j < n; j++) {
            if (graph[i][j] === 1 && isVitited[i][j] === false) {
                isVitited[i][j] = true
                res++
                bfs(graph, isVitited, i, j)
            }
        }
    }
    console.log(res)
}()

function bfs(graph, isVitited, i, j) {
    // 广度遍历此节点
    let direction = [[1, 0], [-1, 0], [0, 1], [0, -1]],
        queue = [[i, j]];

    while (queue.length > 0) {
        let [x, y] = queue.pop()
        for (let [left, right] of direction) {
            let newX = x + left,
                newY = y + right;
            if (newX < 0 || newX >= graph.length || newY < 0 || newY >= graph[0].length) continue
            if (graph[newX][newY] === 1 && isVitited[newX][newY] === false) {
                queue.push([newX, newY])
                isVitited[newX][newY] = true
            }
        }
    }
}



/**
 * leetcode版深搜
 * @param {character[][]} grid
 * @return {number}
 */
var numIslands = function (grid) {
    let isVisited = new Array(grid.length).fill(0).map(() => new Array(grid[0].length).fill(false)),
        res = 0;

    for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[0].length; j++) {
            if (grid[i][j] === "1" && isVisited[i][j] === false) {
                isVisited[i][j] = true
                res++
                dfs(grid, isVisited, i, j)
            }
        }
    }
    return res
};

function dfs(grid, isVisited, i, j) {
    let direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    for (let [x, y] of direction) {
        let newX = i + x,
            newY = j + y;
        if (newX < 0 || newY < 0 || newX >= grid.length || newY >= grid[0].length) continue
        if (grid[newX][newY] === "1" && isVisited[newX][newY] === false) {
            isVisited[newX][newY] = true
            dfs(grid, isVisited, newX, newY)
        }
    }
}


/**
 * 深搜不维护bool数组
 * @param {character[][]} grid
 * @return {number}
 */
var numIslands = function (grid) {
    let res = 0;

    for (let row = 0; row < grid.length; row++) {
        for (let column = 0; column < grid[0].length; column++) {
            if (grid[row][column] === '1') {
                dfs(grid, row, column)
                res++
            }
        }
    }

    return res;
};

const dfs = (grid, row, column) => {
    // 每次遍历到的点重置，如果点的内容会使用到，需维护visited数组
    grid[row][column] = 2
    let direction = [[0, 1], [0, -1], [1, 0], [-1, 0]];
    for (let [x, y] of direction) {
        let newRow = row + x,
            newColumn = column + y;

        if (newRow < 0 || newRow >= grid.length || newColumn < 0 || newColumn >= grid[0].length) continue

        if (grid[newRow][newColumn] === '1') {
            dfs(grid, newRow, newColumn)
        }
    }
}

/**
 * 广搜
 * @param {character[][]} grid
 * @return {number}
 */
var numIslands = function (grid) {
    let res = 0;

    for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[0].length; j++) {
            if (grid[i][j] === "1") {
                res++
                bfs(grid, i, j)
            }
        }
    }
    return res
};

function bfs(grid, i, j) {
    let direction = [[1, 0], [-1, 0], [0, 1], [0, -1]],
        queue = [[i, j]];
    grid[i][j] = "2"
    while (queue.length > 0) {
        let [x, y] = queue.pop()
        for (let [left, right] of direction) {
            let newX = left + x,
                newY = right + y;
            if (newX < 0 || newY < 0 || newX >= grid.length || newY >= grid[0].length) continue
            if (grid[newX][newY] === "1") {
                grid[newX][newY] = "2"
                queue.push([newX, newY])
            }
        }
    }
}


